using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Engine;
using Game;

namespace RuthlessConquest {
    public static class NamesManager {
        public static Random Random = new(0);
        public const string fName = "RCNamesManager";

        public static string[] Prefixes = Names.Prefixes.Replace("\r", "").Split('\n');
        public static string[] Adjectives = Names.Adjectives.Replace("\r", "").Split('\n');
        public static string[] Nouns = Names.Nouns.Replace("\r", "").Split('\n');
        public static string[] Forbidden = Names.Forbidden.Replace("\r", "").Split('\n');
        public static string[] ForbiddenAnywhere = Names.ForbiddenAnywhere.Replace("\r", "").Split('\n');

        public static string GenerateName(int seed) {
            Random.Reset(seed);
            string text = null;
            for (int i = 0; i < 100 || text == null || ValidatePlayerName(text) != null; i++) {
                text = "";
                if (Random.Bool(0.5f)) {
                    text += CapitalizeFirst(Prefixes[Random.Int(Prefixes.Length)]);
                }
                if (Random.Bool(0.5f)) {
                    text += CapitalizeFirst(Nouns[Random.Int(Nouns.Length)]);
                    text += CapitalizeFirst(Nouns[Random.Int(Nouns.Length)]);
                }
                else {
                    text += CapitalizeFirst(Adjectives[Random.Int(Adjectives.Length)]);
                    text += CapitalizeFirst(Nouns[Random.Int(Nouns.Length)]);
                }
            }
            return text;
        }

        public static string ValidatePlayerName(string name) {
            if (name == "KAALUS") {
                return null;
            }
            if (name == null
                || name.Length < 3) {
                return LanguageControl.Get(fName, "1");
            }
            if (name.Length > 16) {
                return LanguageControl.Get(fName, "2");
            }
            //if (name.Count(c => char.IsLetterOrDigit(c) || c == ' ') != name.Length) {
            //return LanguageControl.Get(fName, "3");
            //}
            if (name.Count(c => char.IsUpper(c)) > 3) {
                return LanguageControl.Get(fName, "4");
            }
            if (name.StartsWith(" ")
                || name.EndsWith(" ")) {
                return LanguageControl.Get(fName, "5");
            }
            string nameLower = name.ToLower();
            string nameLowerNoSpaces = nameLower.Replace(" ", "");
            if (Forbidden.Contains(nameLower)) {
                return LanguageControl.Get(fName, "6");
            }
            if (Forbidden.Contains(nameLowerNoSpaces)) {
                return LanguageControl.Get(fName, "6");
            }
            if (ForbiddenAnywhere.Any(f => nameLower.Contains(f))) {
                return LanguageControl.Get(fName, "6");
            }
            if (ForbiddenAnywhere.Any(f => nameLowerNoSpaces.Contains(f))) {
                return LanguageControl.Get(fName, "6");
            }
            if (nameLower.Split(' ').Any(w => Forbidden.Contains(w))) {
                return LanguageControl.Get(fName, "6");
            }
            return null;
        }

        public static void ShowSetPlayerNameDialog(ContainerWidget parentWidget, Action handler) {
            string text = string.IsNullOrEmpty(SettingsManager.PlayerName) ? GenerateName(new Random().Int()) : SettingsManager.PlayerName;
            DialogsManager.ShowDialog(
                parentWidget,
                new TextBoxDialog(
                    LanguageControl.Get(fName, "7"),
                    text,
                    16,
                    delegate(string s) {
                        if (s != null) {
                            s = s.Trim();
                            if (s == string.Empty) {
                                SettingsManager.PlayerName = GenerateName(MathUtils.Hash(Time.FrameIndex));
                            }
                            else {
                                IEnumerable<byte> source = Encoding.UTF8.GetBytes(s)
                                .Concat(
                                    new byte[] {
                                        11,
                                        22,
                                        33,
                                        44,
                                        55,
                                        66,
                                        77,
                                        88,
                                        99
                                    }
                                );
                                if (SHA256.Create()
                                    .ComputeHash(source.ToArray())
                                    .SequenceEqual(
                                        new byte[] {
                                            139,
                                            23,
                                            161,
                                            189,
                                            209,
                                            58,
                                            22,
                                            134,
                                            255,
                                            22,
                                            179,
                                            41,
                                            74,
                                            236,
                                            236,
                                            50,
                                            56,
                                            7,
                                            55,
                                            253,
                                            203,
                                            44,
                                            150,
                                            202,
                                            108,
                                            186,
                                            7,
                                            57,
                                            71,
                                            191,
                                            73,
                                            147
                                        }
                                    )) {
                                    s = "Kaalus";
                                }
                                else if (s.ToLower().Replace(" ", "").Contains("kaalus")) {
                                    s = "FalseKaalus";
                                }
                                string text2 = ValidatePlayerName(s);
                                if (text2 != null) {
                                    DialogsManager.ShowDialog(
                                        parentWidget,
                                        new MessageDialog(LanguageControl.Get(fName, "8"), text2, LanguageControl.Ok, null, null)
                                    );
                                }
                                else {
                                    SettingsManager.PlayerName = s;
                                    handler?.Invoke();
                                }
                            }
                        }
                    }
                )
            );
        }

        public static void EnsureValidPlayerNameExists(Action handler) {
            if (ValidatePlayerName(SettingsManager.PlayerName) != null) {
                ShowSetPlayerNameDialog(null, handler);
            }
            else {
                handler?.Invoke();
            }
        }

        public static string CapitalizeFirst(string s) {
            if (s.Length <= 0) {
                return string.Empty;
            }
            return char.ToUpperInvariant(s[0]) + s.Substring(1);
        }
    }
}